package com.stellar.circle.domain.sComment.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.stellar.auth.api.dto.UserInfoDTO;
import com.stellar.circle.basic.entity.SComment;
import com.stellar.circle.basic.entity.SPost;
import com.stellar.circle.basic.service.SCommentLikeService;
import com.stellar.circle.basic.service.SCommentSensitiveLogService;
import com.stellar.circle.basic.service.SCommentService;
import com.stellar.circle.basic.service.SPostService;
import com.stellar.circle.constants.ErrorCodeConstants;
import com.stellar.circle.constants.CircleConstants;
import com.stellar.circle.controller.admin.sComment.vo.*;
import com.stellar.circle.controller.miniApp.sComment.vo.SCommentTreeResponseVO;
import com.stellar.circle.convert.SCommentConvert;
import com.stellar.circle.domain.sComment.SCommentDomainService;

import com.stellar.circle.enums.PostSourceTypeEnums;
import com.stellar.circle.rpc.UserRPC;
import com.stellar.core.context.LoginContextHolder;
import com.stellar.web.core.bean.PageResult;
import com.stellar.web.core.enums.IsDeletedFlagEnum;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.stellar.core.util.ServiceExceptionUtil.exception;

/**
 * 评论表领域服务实现
 *
 * @author Jqchan
 * @version 1.0
 * @date 2025-05-19 14:52:28
 */
@Service
public class SCommentDomainServiceImpl implements SCommentDomainService {

    @Resource
    private SCommentService sCommentService;

    @Resource
    private SPostService sPostService;

    @Resource
    private UserRPC userRPC;

    @Resource
    private SCommentSensitiveLogService sCommentSensitiveLogService;

    @Resource
    private SCommentLikeService sCommentLikeService;

    @Override
    public PageResult<SCommentResponseVO> page(SCommentRequestPageVO requestPageVO) {
        PageResult<SCommentResponseVO> pageResult = new PageResult<>();
        SComment queryEntity = SCommentConvert.INSTANCE.convert(requestPageVO);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        List<SComment> entities = sCommentService.page(queryEntity,
                requestPageVO.getStart(), requestPageVO.getPageSize());

        if (entities.isEmpty()) {
            return pageResult;
        }

        Long count = sCommentService.count(queryEntity);
        List<SCommentResponseVO> vos = SCommentConvert.INSTANCE.convertEntityToRespList(entities);

        // 收集批量查询所需数据
        Set<Long> postIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();
        Set<Long> parentCommentIds = new HashSet<>();

        for (SComment comment : entities) {
            // 帖子
            if (PostSourceTypeEnums.POST.getType().equals(comment.getSourceType())) {
                postIds.add(comment.getSourceId());
            } else if (PostSourceTypeEnums.IDLE.getType().equals(comment.getSourceType())) {
                // 闲置
            }
            userIds.add(comment.getUserId());
            if (comment.getParentId() != null) {
                parentCommentIds.add(comment.getParentId());
            }
        }

        // 批量查询帖子标题
        Map<Long, String> postTitleMap = Collections.emptyMap();
        if (!postIds.isEmpty()) {
            List<SPost> posts = sPostService.batchQueryByIds(postIds);
            postTitleMap = posts.stream()
                    .collect(Collectors.toMap(SPost::getId, SPost::getTitle));
        }

        // 批量查询父评论的用户ID
        Map<Long, SComment> parentCommentMap = Collections.emptyMap();
        if (!parentCommentIds.isEmpty()) {
            List<SComment> parentComments = sCommentService.batchQueryByParentIds(parentCommentIds);
            parentCommentMap = parentComments.stream()
                    .filter(c -> IsDeletedFlagEnum.UN_DELETED.getVal().equals(c.getIsDeleted()))
                    .collect(Collectors.toMap(SComment::getId, c -> c));
        }

        // 收集所有需要查询的用户ID（评论者+被回复者）
        Set<Long> allUserIds = new HashSet<>(userIds);
        allUserIds.addAll(parentCommentMap.values().stream()
                .map(SComment::getUserId)
                .collect(Collectors.toSet()));

        Map<Long, String> userNicknameMap = Collections.emptyMap();
        if (!allUserIds.isEmpty()) {
            List<UserInfoDTO> userInfoDTOS = userRPC.batchQueryByIds(new ArrayList<>(allUserIds));
            userNicknameMap = userInfoDTOS.stream().collect(Collectors.toMap(UserInfoDTO::getId, UserInfoDTO::getNickName));
        }

        // 填充数据
        for (SCommentResponseVO vo : vos) {
            // 设置图片
            if (vo.getImages() != null) {
                vo.setCommentImages(JSONUtil.toList(vo.getImages(), String.class));
            }

            // 设置帖子标题
            if (PostSourceTypeEnums.POST.getType().equals(vo.getSourceType())) {
                vo.setPostTitle(postTitleMap.getOrDefault(vo.getSourceId(), ""));
            }

            // 设置评论者名称
            vo.setCommenter(userNicknameMap.getOrDefault(vo.getUserId(), ""));

            // 设置回复者名称
            if (vo.getParentId() != null) {
                SComment parentComment = parentCommentMap.get(vo.getParentId());
                if (parentComment != null) {
                    // 设置被回复者昵称
                    vo.setReplyer(userNicknameMap.getOrDefault(parentComment.getUserId(), ""));
                    // 设置被回复的评论内容
                    vo.setReplyContent(parentComment.getContent());
                }
            }
        }

        pageResult.setResult(vos);
        pageResult.setTotal(count.intValue());
        return pageResult;
    }

    @Override
    public Boolean update(SCommentRequestVO requestVO) {
        SComment entity = SCommentConvert.INSTANCE.convert(requestVO);
        // 处理图片
        if (CollectionUtil.isNotEmpty(requestVO.getCommentImages())) {
            entity.setImages(JSONUtil.toJsonStr(requestVO.getCommentImages()));
        }
        return sCommentService.update(entity) != 0;
    }

    @Override
    public Boolean delete(Long id) {
        SComment entity = sCommentService.queryById(id);
        entity.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        // 根据类型操作相关评论数
        if (PostSourceTypeEnums.POST.getType().equals(entity.getSourceType())) { // 帖子
            SPost sPost = sPostService.queryById(entity.getSourceId());
            sPost.setCommentCount(sPost.getCommentCount() - 1);
            sPostService.update(sPost);
        }
        if (PostSourceTypeEnums.IDLE.getType().equals(entity.getSourceType())) { // 闲置

        }

        return sCommentService.update(entity) != 0;
    }

    @Override
    // TODO 调用风控处理 - 设置是否隐藏，处理评论状态
    public Boolean insert(SCommentRequestVO requestVO) {
        SComment entity = SCommentConvert.INSTANCE.convert(requestVO);
        Long userId = LoginContextHolder.getUserId();
        entity.setUserId(userId);

        // 处理图片
        if (CollectionUtil.isNotEmpty(requestVO.getCommentImages())) {
            entity.setImages(JSONUtil.toJsonStr(requestVO.getCommentImages()));
        }

        // 设置初始值
        entity.setReplyCount(0);
        entity.setLikeCount(0);
        entity.setCommentStatus(CircleConstants.COMMENT_STATUS_PUBLISHED);

        // 处理评论层级关系
        handleCommentHierarchy(entity);

        // 插入评论
        boolean success = sCommentService.insert(entity) > 0;

        // 异步更新关联数据（避免事务内多次写操作）
        if (success) {
            CompletableFuture.runAsync(() -> {

                // 更新来源评论数
                updateSourceCommentCount(entity.getSourceType(), entity.getSourceId(), 1);

                // 更新父评论回复数
                if (entity.getParentId() != null) {
                    updateParentCommentReplyCount(entity.getParentId(), 1);
                }
            });
        }

        return success;

    }


    /**
     * 处理评论层级关系（设置rootId）
     */
    private void handleCommentHierarchy(SComment comment) {
        if (comment.getParentId() == null) {
            // 一级评论：初始设置rootId为0（插入后更新）
            comment.setRootId(0L);
        } else {
            // 回复评论：查询父评论获取rootId
            SComment parent = sCommentService.queryById(comment.getParentId());
            if (parent == null) {
                throw exception(ErrorCodeConstants.CIRCLE_COMMENT_NOT_EXIST);
            }

            // 设置rootId（父评论的rootId或自身ID）
            comment.setRootId(parent.getRootId() != null && parent.getRootId() > 0 ?
                    parent.getRootId() : parent.getId());
        }
    }

    /**
     * 更新来源（帖子/闲置）评论数
     */
    private void updateSourceCommentCount(String sourceType, Long sourceId, int delta) {
        if (PostSourceTypeEnums.POST.getType().equals(sourceType)) {
            // 使用原子操作更新帖子评论数
            sPostService.updateCommentCount(sourceId, delta);
        } else if (PostSourceTypeEnums.IDLE.getType().equals(sourceType)) {
            // 更新闲置物品评论数
//            sIdleService.updateCommentCount(sourceId, delta);
        }
    }

    /**
     * 更新父评论回复数（原子操作）
     */
    private void updateParentCommentReplyCount(Long parentId, int delta) {
        sCommentService.updateReplyCount(parentId, delta);
    }


    @Override
    public SCommentResponseVO get(Long id) {
        SComment entity = sCommentService.queryById(id);
        SCommentResponseVO sCommentResponseVO = SCommentConvert.INSTANCE.convert(entity);
        if (entity != null && Strings.isNotBlank(entity.getImages())) {
            sCommentResponseVO.setCommentImages(JSONUtil.toList(entity.getImages(), String.class));
        }
        return sCommentResponseVO;
    }


    @Override
    public SCommentDataStatisticsVO countByCondition(SCommentRequestVO requestVO) {
        // 解析时间范围
        LocalDateTime beginTime = null;
        LocalDateTime endTime = null;
        if (requestVO.getBeginTime() != null || requestVO.getEndTime() != null) {
            beginTime = requestVO.getBeginTime();
            endTime = requestVO.getEndTime();
        }


        // 获取当前周期统计数据
        CommentStatistics currentStats = sCommentService.getCommentStatistics(
                beginTime,
                endTime,
                requestVO.getSourceType(),
                requestVO.getIsAnonymous(),
                requestVO.getCommentStatus()
        );

        // 计算增长率需要的对比周期
        LocalDateTime prevBeginTime = null;
        LocalDateTime prevEndTime = null;
        if (beginTime != null && endTime != null) {
            long durationDays = ChronoUnit.DAYS.between(beginTime, endTime);
            prevBeginTime = beginTime.minusDays(durationDays + 1);
            prevEndTime = beginTime.minusSeconds(1);
        }

        // 获取对比周期统计数据
        CommentStatistics prevStats = sCommentService.getCommentStatistics(
                prevBeginTime,
                prevEndTime,
                requestVO.getSourceType(),
                requestVO.getIsAnonymous(),
                requestVO.getCommentStatus()
        );

        // 获取风控评论数
        Long riskCount = sCommentSensitiveLogService.countRiskComments(
                beginTime,
                endTime,
                requestVO.getSourceType(),
                requestVO.getIsAnonymous()
        );

        // 计算增长率
        double growthRate = 0.0;
        if (prevStats != null && prevStats.getTotalCount() != null && prevStats.getTotalCount() > 0) {
            long currentTotal = currentStats.getCommentCount() + currentStats.getReplyCount();
            long prevTotal = prevStats.getCommentCount() + prevStats.getReplyCount();
            growthRate = ((double) (currentTotal - prevTotal) / prevTotal) * 100;
        }

        // 构建返回结果
        SCommentDataStatisticsVO result = new SCommentDataStatisticsVO();
        result.setCommentCount(currentStats.getTotalCount());
        result.setReplyCount(currentStats.getReplyCount());
        result.setGrowthRate(growthRate);
        result.setCommentRiskCount(riskCount != null ? riskCount : 0L);

        return result;
    }

    @Override
    public List<DailyCommentStatisticsVO> getDailyCommentStatistics() {
        // 计算时间范围（过去7天，包括今天）
        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusDays(6);

        // 生成日期列表（确保连续7天）
        List<LocalDate> dateRange = IntStream.range(0, 7)
                .mapToObj(startDate::plusDays)
                .collect(Collectors.toList());

        // 获取数据库中的统计数据
        List<DailyCommentStatisticsVO> dbResults = sCommentService.getDailyCommentCounts(
                startDate.atStartOfDay(),
                endDate.plusDays(1).atStartOfDay()
        );

        // 创建日期->计数的映射
        Map<String, Long> dateCountMap = dbResults.stream()
                .collect(Collectors.toMap(
                        DailyCommentStatisticsVO::getDate,
                        DailyCommentStatisticsVO::getCount
                ));

        // 构建完整7天的数据（缺失的日期补0）
        return dateRange.stream()
                .map(date -> {
                    String dateStr = date.format(DateTimeFormatter.ofPattern("MM-dd"));
                    Long count = dateCountMap.getOrDefault(dateStr, 0L);
                    return new DailyCommentStatisticsVO(dateStr, count);
                })
                .collect(Collectors.toList());
    }

    @Override
    public CommentTreeVO getCommentTree(String sourceType, Long sourceId) {
        // 获取总评论数
        List<SCommentWithUserInfo> allComments = sCommentService.selectAllCommentsWithUserInfo(sourceType, sourceId);
        Long totalCount = (long) allComments.size();

        // 过滤出一级评论
        List<SCommentWithUserInfo> rootComments = sCommentService.selectRootComments(sourceType, sourceId);

        // 构建评论树
        List<CommentTreeNodeVO> tree = new ArrayList<>();
        Map<Long, CommentTreeNodeVO> rootCommentMap = new HashMap<>();

        // 构建一级评论
        for (SCommentWithUserInfo comment : rootComments) {
            CommentTreeNodeVO node = buildRootComment(comment);
            tree.add(node);
            rootCommentMap.put(comment.getId(), node);
        }

        // 挂载二级评论
        for (SCommentWithUserInfo comment : allComments) {
            if (comment.getParentId() != null && rootCommentMap.containsKey(comment.getRootId())) {
                SubCommentVO sub = buildSubComment(comment, allComments);
                rootCommentMap.get(comment.getRootId()).getReplies().add(sub);
            }
        }

        return new CommentTreeVO(totalCount, tree);
    }


    private CommentTreeNodeVO buildRootComment(SCommentWithUserInfo comment) {
        CommentTreeNodeVO vo = SCommentConvert.INSTANCE.convert(comment);

        UserInfoDTO userInfo = getUserInfo(comment.getUserId());
        vo.setUserInfo(userInfo);
        vo.setIsCurrentUser(LoginContextHolder.getUserId() != null && LoginContextHolder.getUserId().equals(comment.getUserId()));
        vo.setLiked(sCommentLikeService.checkLikeStatus(comment.getId(), LoginContextHolder.getUserId()));
        vo.setReplies(new ArrayList<>());

        // 处理评论图片
        if (vo.getImages() != null) {
            vo.setCommentImages(JSONUtil.toList(comment.getImages(), String.class));
        }

        return vo;
    }

    private SubCommentVO buildSubComment(SCommentWithUserInfo comment, List<SCommentWithUserInfo> allComments) {
        SubCommentVO vo = new SubCommentVO();
        vo.setId(comment.getId());
        vo.setUserId(comment.getUserId());
        vo.setContent(comment.getContent());
        vo.setCreateTime(comment.getCreateTime());

        UserInfoDTO userInfo = getUserInfo(comment.getUserId());
        vo.setUserInfo(userInfo);
        vo.setIsCurrentUser(LoginContextHolder.getUserId() != null && LoginContextHolder.getUserId().equals(comment.getUserId()));
        vo.setLiked(sCommentLikeService.checkLikeStatus(comment.getId(), LoginContextHolder.getUserId()));

        // 判断是否是回复二级评论
        if (comment.getParentId() != null) {
            Optional<SCommentWithUserInfo> parentOpt = allComments.stream()
                    .filter(c -> c.getId().equals(comment.getParentId()))
                    .findFirst();

            if (parentOpt.isPresent()) {
                SCommentWithUserInfo parent = parentOpt.get();
                // 只有当 parent 不是一级评论时，才设置 replyTargetUser
                if (parent.getParentId() != null) { // 表示 parent 是二级评论
                    vo.setReplyTargetUser(getUserInfo(parent.getUserId()));
                }
            }
        }

        // 处理评论图片
        if (comment.getImages() != null) {
            vo.setCommentImages(JSONUtil.toList(comment.getImages(), String.class));
        }

        return vo;
    }

    private UserInfoDTO getUserInfo(Long userId) {
        return userRPC.queryUserInfoByUid(userId);
    }

}
